package com.piggy.logi.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.piggy.common.core.constant.SecurityConstants;
import com.piggy.common.core.exception.GlobalException;
import com.piggy.common.core.utils.PageUtils;
import com.piggy.common.core.utils.StringUtils;
import com.piggy.common.core.utils.sql.SqlUtil;
import com.piggy.common.core.web.page.PagePlus;
import com.piggy.common.core.web.page.TableDataInfo;
import com.piggy.common.satoken.utils.SecurityUtils;
import com.piggy.logi.sys.api.domain.LogiSysUser;
import com.piggy.logi.sys.bo.LogiCarrierDriverExtEditBo;
import com.piggy.logi.sys.bo.LogiCarrierDriverLineQueryBo;
import com.piggy.logi.sys.bo.LogiCarrierDriverQueryBo;
import com.piggy.logi.sys.bo.LogiDriverCanScheduleQueryBo;
import com.piggy.logi.sys.domain.LogiCarrierDriver;
import com.piggy.logi.sys.mapper.LogiCarrierDriverMapper;
import com.piggy.logi.sys.service.ILogiCarrierDriverLineService;
import com.piggy.logi.sys.service.ILogiCarrierDriverService;
import com.piggy.logi.sys.service.ILogiSysRoleService;
import com.piggy.logi.sys.service.ILogiSysUserService;
import com.piggy.logi.sys.vo.LogiCarrierDriverExtVo;
import com.piggy.logi.sys.vo.LogiCarrierDriverLineExtVo;
import com.piggy.sys.api.RemoteDistrictService;
import com.piggy.sys.api.RemoteSmsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 承运商司机信息Service业务层处理
 */
@Slf4j
@Service
public class LogiCarrierDriverServiceImpl extends ServiceImpl<LogiCarrierDriverMapper, LogiCarrierDriver> implements ILogiCarrierDriverService {

    @Resource
    private RemoteDistrictService remoteDistrictService;
    @Resource
    private ILogiSysUserService logiSysUserService;
    @Resource
    private ILogiCarrierDriverLineService driverLineService;
    @Resource
    private ILogiSysUserService userService;
    @Resource
    private ILogiSysRoleService roleService;

    @Resource
    private RemoteSmsService smsService;

    @Override
    public LogiCarrierDriverExtVo queryById(Long id) {
        LogiCarrierDriverExtVo carrierDriverVo = getVoById(id, LogiCarrierDriverExtVo.class);
        if (ObjectUtil.isEmpty(carrierDriverVo)) {
            return carrierDriverVo;
        }
        List<String> districtIds = Lists.newArrayList(ObjectUtil.defaultIfNull(carrierDriverVo.getAddressDistrictId(),0L).toString());
        Map<String, String> districtMap = remoteDistrictService.getDistrictMap(districtIds, SecurityConstants.INNER).getData();
        carrierDriverVo.setAddressDistrictName(districtMap.get(ObjectUtil.defaultIfNull(carrierDriverVo.getAddressDistrictId(),0L).toString()));
        // 长跑路线
        LogiCarrierDriverLineQueryBo bo = new LogiCarrierDriverLineQueryBo();
        bo.setCarrierDriverIds(Lists.newArrayList(carrierDriverVo.getDriverId()));
        bo.setLineType(1);
        List<LogiCarrierDriverLineExtVo> driverLineExtVos = driverLineService.queryList(bo);

        // 获取账号状态数据
        if (carrierDriverVo.getUserId() != null) {
            List<LogiSysUser> logiSysUserList = logiSysUserService.selectUserByIds(Lists.newArrayList(carrierDriverVo.getUserId()));
            Map<Long, LogiSysUser> userMap = logiSysUserList.stream().collect(Collectors.toMap(LogiSysUser::getUserId, Function.identity(), (a, b) -> a));
            LogiSysUser sysUser = userMap.get(carrierDriverVo.getUserId());
            if (sysUser != null) {
                carrierDriverVo.setAccountStatus(sysUser.getStatus());
                carrierDriverVo.setSysUser(sysUser);
            }
        }

        carrierDriverVo.setDriverLineList(driverLineExtVos);
        return carrierDriverVo;
    }

    @Override
    public TableDataInfo<LogiCarrierDriverExtVo> queryPageList(LogiCarrierDriverQueryBo bo) {
        PagePlus<LogiCarrierDriver, LogiCarrierDriverExtVo> result = pageVo(PageUtils.buildPagePlus(bo, true), buildQueryWrapper(bo), LogiCarrierDriverExtVo.class);
        List<LogiCarrierDriverExtVo> pageListVos = result.getRecordsVo();
        fillData(pageListVos);
        result.setRecordsVo(pageListVos);

        return PageUtils.buildDataInfo(result);
    }

    private List<LogiCarrierDriverExtVo> fillData(List<LogiCarrierDriverExtVo> driverExtVos) {
        // 获取地址数据
        List<String> districtIds = driverExtVos.stream().map(item -> item.getAddressDistrictId().toString()).distinct().collect(Collectors.toList());
        Map<String, String> districtNameMap = remoteDistrictService.getDistrictMap(districtIds, SecurityConstants.INNER).getData();
        // 获取账号状态数据
        List<Long> userIdList = driverExtVos.stream().map(LogiCarrierDriverExtVo::getUserId).distinct().collect(Collectors.toList());
        if (CollUtil.isEmpty(userIdList)) {
            userIdList = Lists.newArrayList(0L);
        }
        List<LogiSysUser> logiSysUserList = logiSysUserService.selectUserByIds(userIdList);
        Map<Long, LogiSysUser> userMap = logiSysUserList.stream().collect(Collectors.toMap(LogiSysUser::getUserId, Function.identity(), (a, b) -> a));

        // 长跑路线
        List<Long> carrierDriverIds = driverExtVos.stream().map(LogiCarrierDriverExtVo::getDriverId).collect(Collectors.toList());
        LogiCarrierDriverLineQueryBo bo = new LogiCarrierDriverLineQueryBo();
        bo.setCarrierDriverIds(carrierDriverIds);
        bo.setLineType(1);
        List<LogiCarrierDriverLineExtVo> driverLineExtVos = driverLineService.queryList(bo);
        Map<Long, List<LogiCarrierDriverLineExtVo>> dricerLineMap = driverLineExtVos.stream().collect(Collectors.groupingBy(LogiCarrierDriverLineExtVo::getCarrierDriverId));
        // 开通账户数据
        driverExtVos.forEach(vo -> {
            vo.setAddressDistrictName(districtNameMap.get(vo.getAddressDistrictId().toString()));
            LogiSysUser sysUser = userMap.get(vo.getUserId());
            if (sysUser != null) {
                vo.setAccountStatus(sysUser.getStatus());
                vo.setSysUser(sysUser);
            }
            vo.setDriverLineList(dricerLineMap.get(vo.getDriverId()));
        });

        return driverExtVos;
    }

    @Override
    public List<LogiCarrierDriverExtVo> queryList(LogiCarrierDriverQueryBo bo) {
        List<LogiCarrierDriverExtVo> driverExtVos = listVo(buildQueryWrapper(bo), LogiCarrierDriverExtVo.class);
        fillData(driverExtVos);
        return driverExtVos;
    }

    private LambdaQueryWrapper<LogiCarrierDriver> buildQueryWrapper(LogiCarrierDriverQueryBo bo) {
        LambdaQueryWrapper<LogiCarrierDriver> lqw = Wrappers.lambdaQuery();
        lqw.like(StrUtil.isNotBlank(bo.getDriverName()), LogiCarrierDriver::getDriverName, bo.getDriverName());
        lqw.eq(bo.getDriverType() != null, LogiCarrierDriver::getDriverType, bo.getDriverType());
        lqw.eq(bo.getAddressDistrictId() != null, LogiCarrierDriver::getAddressDistrictId, bo.getAddressDistrictId());
        lqw.eq(ObjectUtil.isNotEmpty(bo.getUserId()), LogiCarrierDriver::getUserId, bo.getUserId());
        lqw.like(StrUtil.isNotBlank(bo.getPhoneNumber()), LogiCarrierDriver::getPhoneNumber, bo.getPhoneNumber());
        if (StringUtils.isNotBlank(bo.getCreateTimeStr())) {
            lqw.apply("DATE_FORMAT(create_time, '%Y-%m-%d') = {0}", bo.getCreateTimeStr());
        }
        if (StringUtils.isNotBlank(bo.getDriverLicenseExpireDateStr())) {
            lqw.apply("DATE_FORMAT(driver_license_expire_date, '%Y-%m-%d') = {0}", bo.getDriverLicenseExpireDateStr());
        }

        lqw.in(CollUtil.isNotEmpty(bo.getDriverIds()), LogiCarrierDriver::getDriverId, bo.getDriverIds());
        // 部门数据权限过滤
        if (ObjectUtil.isNotNull(bo.getDeptId())) {
            SqlUtil.dataPermissionFilter(lqw, bo.getDeptId());
        }
        return lqw;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByAddBo(LogiCarrierDriverExtEditBo bo) {
        LogiCarrierDriver driver = baseMapper.selectByPhone(bo.getMainDeptId(), bo.getPhoneNumber());
        if (ObjectUtil.isNotEmpty(driver)) {
            throw new GlobalException("手机号已经存在，不能添加了");
        }
        LogiCarrierDriver add = BeanUtil.toBean(bo, LogiCarrierDriver.class);
        add.setOtherAttachment(bo.getOtherAttachment());
        /*if (StrUtil.isNotBlank(bo.getOpenAccount()) && (bo.getEnableStatus() == 1)) {
            // check open account
            LogiSysUser sysUser = logiSysUserService.selectUserByPhoneAndDept(bo.getOpenAccount(), bo.getDeptId().toString());
            if (sysUser != null) {
                LogiCarrierDriver vo = getOne(new LambdaQueryWrapper<LogiCarrierDriver>().eq(LogiCarrierDriver::getUserId, sysUser.getUserId()).last("limit 1"));
                if (ObjectUtil.isNotEmpty(vo)) {
                    throw new GlobalException("当前账号已开通");
                }
            }
        }*/
        boolean ret = save(add);
        if (StrUtil.isNotEmpty(bo.getOpenAccount()) && (bo.getEnableStatus() == 1)) {
            // new user
            LogiSysUser newUser = logiSysUserService.selectUserByPhoneAndDept(bo.getOpenAccount(), bo.getMainDeptId().toString());
            if (ObjectUtil.isEmpty(newUser)) {
                newUser = new LogiSysUser().setUserName(bo.getDriverName()).setDeptId(SecurityUtils.getDeptId()).setOrignalPwd(SecurityUtils.randomPwd(12));
                newUser.setPassword(SecurityUtils.encryptPassword(newUser.getOrignalPwd()));
                Long roleId = roleService.selectRoleByKey(SecurityUtils.AdminRoleEnum.DRIVER.getRole()).getRoleId();
                newUser.setPhonenumber(bo.getOpenAccount()).setRoleIds(Lists.newArrayList(roleId));
                userService.insertUser(newUser);
            }

            LogiCarrierDriver update = new LogiCarrierDriver();
            update.setDriverId(add.getDriverId());
            update.setUserId(newUser.getUserId());
            updateById(update);
            LogiSysUser user = userService.selectUserById(newUser.getUserId());
            try {
                smsService.createAccount(user.getPhonenumber(), user.getOrignalPwd(), bo.getMainDeptId()+"", DatePattern.NORM_DATE_FORMAT.format(newUser.getCreateTime()), SecurityConstants.INNER);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }

            // 发送短信
//            LoginUser<LogiSysUser> loginUser = (LoginUser<LogiSysUser>)SecurityUtils.getOauthUser();
//            R<Boolean> smsSendR = smsService.createAccount(newUser.getPhonenumber(), newUser.getOrignalPwd(),loginUser.getSysUser().getDept().getDeptName(), SecurityConstants.INNER);
//            FeignResultUtils.throwIfFailed(smsSendR);
        }
        if (CollUtil.isEmpty(bo.getDriverLineList())) {
            return ret;
        }
        bo.getDriverLineList().forEach(item -> {
            item.setLineType(1);
            item.setCarrierDriverId(add.getDriverId());
        });
        driverLineService.batchByAddBo(bo.getDriverLineList());

        return ret;
    }

    @Override
    public Boolean updateByEditBo(LogiCarrierDriverExtEditBo bo) {
        if (bo.getDriverId() == null) {
            throw new GlobalException("修改ID不能为空");
        }
        LogiCarrierDriver carrierDriverDB = getById(bo.getDriverId());
        if (carrierDriverDB == null) {
            throw new GlobalException("数据不存在");
        }
        LogiCarrierDriver driver = baseMapper.selectByPhone(bo.getMainDeptId(), bo.getPhoneNumber());
        if (ObjectUtil.isNotEmpty(driver) && (!Objects.equals(driver.getDriverId(), carrierDriverDB.getDriverId()))) {
            throw new GlobalException("手机号已经存在，不能修改了");
        }
        /*if (StrUtil.isNotBlank(bo.getOpenAccount()) && (bo.getEnableStatus() == 1)) {
            // check open account
            LogiSysUser sysUser = logiSysUserService.selectUserByPhoneAndDept(bo.getOpenAccount(), bo.getDeptId().toString());
            if (sysUser != null) {
                LogiCarrierDriver vo = getOne(new LambdaQueryWrapper<LogiCarrierDriver>().eq(LogiCarrierDriver::getUserId, sysUser.getUserId()).last("limit 1"));
                if (ObjectUtil.isNotEmpty(vo)) {
                    throw new GlobalException("当前账号已开通");
                }
            }
        }*/
        LogiCarrierDriver update = BeanUtil.toBean(bo, LogiCarrierDriver.class);
        boolean ret = updateById(update);
        if (StrUtil.isNotEmpty(bo.getOpenAccount()) && (bo.getEnableStatus() == 1)) {
            // new user
            LogiSysUser newUser = logiSysUserService.selectUserByPhoneAndDept(bo.getOpenAccount(), bo.getMainDeptId().toString());
            if (ObjectUtil.isEmpty(newUser)) {
                newUser = new LogiSysUser().setUserName(bo.getDriverName()).setDeptId(SecurityUtils.getDeptId()).setOrignalPwd(SecurityUtils.randomPwd(12));
                newUser.setPassword(SecurityUtils.encryptPassword(newUser.getOrignalPwd()));
                Long roleId = roleService.selectRoleByKey(SecurityUtils.AdminRoleEnum.DRIVER.getRole()).getRoleId();
                newUser.setPhonenumber(bo.getOpenAccount()).setRoleIds(Lists.newArrayList(roleId));
                userService.insertUser(newUser);

                // 发送短验证码
                LogiSysUser user = userService.selectUserById(newUser.getUserId());
                try {
                    smsService.createAccount(user.getPhonenumber(), user.getOrignalPwd(), SecurityUtils.getMainDeptId()+"", DatePattern.NORM_DATE_FORMAT.format(newUser.getCreateTime()), SecurityConstants.INNER);
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }
            }
            update.setUserId(newUser.getUserId());
            updateById(update);

            // 发送短信
//            LoginUser<LogiSysUser> loginUser = (LoginUser<LogiSysUser>)SecurityUtils.getOauthUser();
//            R<Boolean> smsSendR = smsService.createAccount(newUser.getPhonenumber(), newUser.getOrignalPwd(),loginUser.getSysUser().getDept().getDeptName(), SecurityConstants.INNER);
//            FeignResultUtils.throwIfFailed(smsSendR);
        }
        if (CollUtil.isNotEmpty(bo.getDriverLineList())) {
            bo.getDriverLineList().forEach(item -> {
                item.setLineType(1);
                item.setCarrierDriverId(bo.getDriverId());
            });
        }
        driverLineService.batchUpdateByDriverId(bo.getDriverId(), 1, bo.getDriverLineList());
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            if (CollUtil.isEmpty(ids)) {
                throw new GlobalException("修改ID不能为空");
            }
        }
        ids.forEach(t-> {
            LogiCarrierDriver driver = getById(t);
            if (ObjectUtil.isNotEmpty(driver.getUserId())) {
                userService.remove(driver.getUserId());
            }
        });

        return removeByIds(ids);
    }

    @Override
    public List<LogiCarrierDriverExtVo> canScheduleList(LogiDriverCanScheduleQueryBo bo) {
        return fillData(baseMapper.canScheduleList(bo));
    }

}
